/****************************************************************************
** Notice:      Copyright (c) 2000 LSI Logic Corporation - All Rights Reserved
**
** File Name:   osp.c
**
**
** Description: Operating System Portability (OSP) Layer. Functions defined
**              here are referenced by the application, and drivers. These
**              functions serve to isolate the application, and drivers, from
**              the vagaries of different RTOS. The API presented here will be
**              constant, and the are defined to  be wrappers around the
**              corresponding API provided by any particular RTOS.
*****************************************************************************/
#include <sys/time.h>

#include <osp.h>                     /* Prototypes for this module.*/
#include <dbgprint.h>
#include <dbgassrt.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "ostask.h"
#include "OsSem.h"
#include "osmsg.h"
#include "pthread.h"

/* ISR stuff hasn't been ported yet (and likely won't), but just in case... */
U8 OSPInLISR = 0x00;
int rootId;

/*****************************************************************************
** Function: OSPMalloc(): This function is used by application, or driver
** to acquire memory for specific uses. The calling function does not specify
** from where the memory is to be allocated. Instead it simply requests a
** block of memory of a certain size. If a block of memory of this size is
** available, the underlying RTOS will return a pointer to the start of the
** block in question. It is important to realize, that it is the
** responsibility of the application to guard against placing data beyond the
** limit of the allocated segment. If more than one memory region exists for
** allocation to the application, this function will attempt to acquire the
** requested segment from the second, only if the first has been exhausted. In
** either case, the allocation process is transparent to the application.
**
** Inputs:  numberOfBytes, the size of the requested memory segment.
**
** Outputs: Nothing.
**
** Returns: void *, a pointer to the allocated memory.
**          NULL, RTOS specific errors.
**
**
** Note:    Currently this function will only attempt to get memory from one
**          region of memory.
*****************************************************************************/
void *OSPMalloc(U32 numberOfBytes)
{
    void * testPtr;
    /* Make sure we're not in a LISR */
    MP_Assert(OSPInLISR == 0);
    if (OSPInLISR != 0)
    {
        return NULL;
    }
    testPtr = malloc(numberOfBytes);
    return testPtr;
}

/*****************************************************************************
** Function: OSPFree(): This function will return an already allocated segment
** of memory back to the heap space. If more than one memory region exists for
** segment allocation, this function will determine the correct one to which
** the specified segment is to be returned.
**
** Inputs:  ptrToSegment, a pointer to the segment to be returned to the heap
**            This pointer must be the exact same one that was returned during
**            a corresponding OSPMalloc function call.
**
** Outputs: NONE.
**
** Returns: SUCCESS, no errors.
**          OSP_INVALID_MEMORY_POINTER, not a valid segment pointer.
**          FAILURE, RTOS specific errors.
**
** Note:    In the current implementation, only one memory region is available
**          for segment allocation.
*****************************************************************************/
S32 OSPFree(void *ptrToSegment)
{
    /* Make sure we're not in a LISR */
    MP_Assert(OSPInLISR == 0);
    if (OSPInLISR != 0)
    {
        return FAILURE;
    }
    free(ptrToSegment);
    return SUCCESS;
}


/****************************************************************************
** Function OSPInitialize(): Initialize the os portability layer. This is
** called from the application once the Exception Handling Driver, and the
** Timer Driver have been initialized. This is necessary, as this function
** sets up the OS Timer Tick, which will use the Exception Handling driver,
** and the Timer driver.
**
** Inputs:  None.
**
** Outputs: None.
**
** Returns: SUCCESS.
****************************************************************************/
S32 OSPInitialize(void)
{
	extern void OS_SemDataInit();
    task_lockcreat();
	OS_SemDataInit();
    return (SUCCESS);
}


/*****************************************************************************
** Function: OSPQueueCreate(): This function is used to create an RTOS Queue.
** This queue will have a fixed message size of 16bytes. The maximum number of
** messages possible in the queue at any given moment, is determined by the
** parameters passed to this function. It is said to be a fixed length queue,
** with fixed size messages, and with RTOS system buffers pre-allocated to
** handle the worse case message load.
**
** Inputs:  name[], this is the unique four character ASCII name give to the
**            queue to be created.
**          maxQueueLength, this specifies the maximum number of messages that
**            can reside in the Queue at any given moment. When the number of
**            un-read messages in the queue reaches this value, then any
**            subsequent attempts to place a message in this queue will fail.
**          taskWaitMode, this parameter determines how tasks waiting on a
**            message from an empty queue will wait. There are two options
**            for this parameter;
**            WAIT_FIFO - the first task to start pending on the queue, will
**                        receive the message when it arrives.
**            WAIT_PRIO - the highest priority waiting task will receive the
**                        message when it arrives.
**
** Outputs: queueID, a unique handle used to reference this particular queue.
**
** Returns: SUCCESS, Queue created successfully.
**          FAILURE, RTOS specific errors.
*****************************************************************************/
#define  OspQueueBuf_size 16

S32 OSPQueueCreate(char name[], U32 maxQueueLength, U32 taskWaitMode,
                     U32 *queueId)
{
    S32 returnCode;            /* For returning status to caller. */

    returnCode = FAILURE;

    /* Make sure we're not in a LISR */
    MP_Assert(OSPInLISR == 0);
    if (OSPInLISR != 0)
    {
        LOGE("OSPInLISR is err\n");
        return returnCode;
    }

    int  Num = maxQueueLength/OspQueueBuf_size;

    if (taskWaitMode == WAIT_FIFO)
        *queueId = (U32)Os_MsgQCreate(OspQueueBuf_size,Num,0);
    else if (taskWaitMode == WAIT_PRIO)
        *queueId = (U32)Os_MsgQCreate(OspQueueBuf_size,Num,1);

#if 0 // qid == 0 is right
    /* Depending on the status, change the return code */
    if (*queueId != 0)
        returnCode = SUCCESS;
    else
        DBGPrint(DBG_DEBUG_OS,DBG_ERROR,"slq test STOS_MessageQueueCreate err\n");
#endif
    return SUCCESS;
}

/*****************************************************************************
** Function: OSPQueueDelete(): This function will result in the specified
** queue being deleted. All the RTOS system buffers used to hold queue
** messages will be returned to the pool of such buffers. Also, all tasks
** pending on a message from this queue, will unblock returning an error
** indicating that the queue was deleted.
**
** Inputs:  queueId, the unique id of the queue to be deleted.
**
** Outputs: NONE.
**
** Returns: SUCCESS, queue deleted successfully.
**          OSP_WARNING, RTOS specific warnings.
**          FAILURE, RTOS specific errors.
*****************************************************************************/
S32 OSPQueueDelete(U32 queueId)
{
    int err;

    /* Make sure we're not in a LISR */
    MP_Assert(OSPInLISR == 0);
    if (OSPInLISR != 0)
    {
        return FAILURE;
    }

    err = Os_MsgQDelete((int)queueId);
    return err;

}
/**/
static int OspCompareTime(struct timeval  *tv1,
                                struct timeval  *tv2)
{
    int ret = 0 ;
    //LOGD("--->[%s] LINE=%d\n",__FUNCTION__,__LINE__);
    if(tv1->tv_sec > tv2->tv_sec)
    {
        return -1;
    }
    else if(tv1->tv_sec == tv2->tv_sec)
    {
        if(tv1->tv_usec > tv2->tv_usec)
            ret = -1;
        else if(tv1->tv_usec == tv2->tv_usec)
            ret = 0;
        else
            ret = 1;
    }
    else
    {
        ret = 1;
    }
    //LOGD("--->[%s] LINE=%d\n",__FUNCTION__,__LINE__,ret);
    return ret;
}

/*****************************************************************************
** Function: OSPQueueGetMessage(): This function is called to attempt to
** retrieve a message from the specified queue. If a message is present, then
** the RTOS will copy the message into the place holder specified in the
** input parameter list. If no message is present, then depending on the input
** parameters, the calling task will either wait for a timeout, or return
** immediately. In either case, the return code will indicate whether or not
** a message was received. If no message is present, and the task has chosen
** to wait forever, then the calling task will block until a message is posted
** to this queue.
** NOTE: The millSec2Wait period is limited by the interrupt frequency of the
** hardware timer in the system. For that reason, if it is greater than zero,
** it is rounded to the lower period, for which OSP_TIMER_TICK_INT_PERIOD is
** an integral.
**
** Inputs:  queueID, the id of the queue from which the message is to be read.
**          message, a pointer to a message structure - 16 bytes in length.
**          waitMode, this describes how tasks attempting to read from the
**            queue will behave if no message is ready to be read. There are
**            two options for this parameter;
**            TASK_WAIT - indicates that the task will block until a message
**            becomes available in this queue.
**            TASK_NOWAIT - indicates a task will not wait for a message if
**            one is pending when this function call was made. Instead the
**            task will return immediately, with an warning indicating that no
**            message was received.
**          milliSecsToWait, if the first option above (TASK_WAIT) was chosen
**            for the 'waitMode' parameter, then 'milliSecsToWait' specifies the
**            number of operating system timer ticks that the task will block
**            before returning if no message is pending. If the second
**            option is chosen for 'waitMode', then 'milliSecsToWait' will be
**            ignored.
**
** Outputs: NONE.
**
** Returns: SUCCESS, message received successfully.
**          OSP_WARNING, RTOS specific warnings.
**          OSP_NO_MESSAGES_AVAILABLE, no messages were pending.
**          OSP_QUEUE_TIMEOUT, time out while waiting for a message.
**          FAILURE, RTOS specific errors.
*****************************************************************************/
S32 OSPQueueGetMessage(U32 queueId, T_FTAEvent *message,
                         U32 waitMode, U32 milliSecsToWait)
{
    int err = 0;

    /* Make sure we're not in a LISR */
    MP_Assert(OSPInLISR == 0);
    if (OSPInLISR != 0)
    {
        LOGE("OSPQueueGetMessage 3queueId:%X,err:%d\n",queueId,FAILURE);
        return FAILURE;
    }

    if (waitMode == TASK_NOWAIT)
    {
       // LOGE("GT_Os_MsgQReceive start !\n");
        err = Os_MsgQReceive((int)queueId,(char *)message,16,0);
		
    }
    else if (waitMode == TASK_WAIT)
    {
        if(milliSecsToWait)
        {
            err = Os_MsgQReceive((int)queueId,(char *)message,16,milliSecsToWait);
            if(err == 0)
                return SUCCESS;
            else
                {
                LOGE("OSPQueueGetMessage 2queueId:%X,err:%d\n",queueId,err);
                return OSP_QUEUE_TIMEOUT;
            }
        }
        else
            err = Os_MsgQReceive((int)queueId,(char *)message,16,1);

    }
    if(err == 0)
        return SUCCESS;
    else
    {
        return FAILURE;
    }

}

/*****************************************************************************
** Function: OSPQueueSendMessage(): This function will copy a message into the
** specified queue.
**
** Inputs:  queueId, id of the queue into which the message is to be placed.
**          message, a pointer to the structure (16bytes in size) which
**            contains the message.
**
** Outputs: NONE.
**
** Returns: SUCCESS, no errors.
**          OSP_QUEUE_FULL, no room for latest message.
**          FAILURE, RTOS specific errors.
*****************************************************************************/
S32 OSPQueueSendMessage(U32 queueId, T_FTAEvent *message,int wait_mode)
{

    int err;

    /* Make sure we're not in a LISR */
    MP_Assert(OSPInLISR == 0);
    if (OSPInLISR != 0)
    {
        LOGE("OSPQueueSendMessage queueId:%x,err\n",queueId);
        return FAILURE;
    }
    err = Os_MsgQSend((int)queueId,(char *)message,16,wait_mode);
    return err;
}
/*****************************************************************************
** Function: OSPSemaphoreCreate(): This function creates a semaphore with the
** specified name, and with the specified token count. There is a lower limit
** of 0 on the token count, and no upper limit.
**
** Inputs:  name[], a four character ASCII name for this semaphore provided by
**            calling function.
**          initialTokenCount, this is the initial token count for the
**            semaphore being created. This value will determine the maximum
**            number of simultaneous accesses allowed to whatever resource is
**            being protected by the semaphore.
**          taskWaitMode, this parameter determines how tasks will wait on a
**            token from an 'empty' semaphore. There are two options for this
**            parameter;
**            WAIT_FIFO - the first task to start pending on the token, will
**                        receive the token when is made available.
**            WAIT_PRIO - the highest priority task pending on the token,
**                        will receive the token when it is made available.
**
** Outputs: semaphoreId, a unique handle that will be used to reference the
**            created semaphore.
**
** Returns: SUCCESS, semaphore created successfully.
**          FAILURE, RTOS specific errors.
*****************************************************************************/
S32 OSPSemaphoreCreate(char name[], U32 initialTokenCount,
                         U32 taskWaitMode, U32 *semaphoreID)
{
    *semaphoreID = (U32)Os_SemInit((int)initialTokenCount);

    if (*semaphoreID == 0)
        return FAILURE;
    else
        return SUCCESS;
}

/*****************************************************************************
** Function: OSPSemaphoreDelete(): This function deletes the specified
** semaphore. All tasks waiting on a token from this semaphore will unblock
** and return an error indicating that the semaphore was deleted.
**
** Inputs:  NONE.
**
** Outputs: NONE.
**
** Returns: SUCCESS, no errors.
**          OSP_WARNING, RTOS specific warnings.
**          FAILURE, RTOS specific errors.
*****************************************************************************/
S32 OSPSemaphoreDelete(U32 semaphoreID)
{
    return Os_SemDestroy(semaphoreID);
}

/*****************************************************************************
** Function: OSPSemaphoreGetToken(): This function attempts to acquire a token
** from the specified semaphore. If no token is available, then the calling
** task will block until a token becomes available, or until it times-out. If
** a token is available, or becomes available, the calling task will unblock,
** and enter the ready state. At this point the calling task has access to the
** protected resource.
** NOTE: The millSec2Wait period is limited by the interrupt frequency of the
** hardware timer in the system. For that reason, if it is greater than zero,
** it is rounded to the lower period, for which OSP_TIMER_TICK_INT_PERIOD is
** an integral.
**
** Inputs:  semaphoreId, a unique handle referencing a specific semaphore.
**          waitMode, specifies how the calling function is to wait on the
**            semaphore token in question. There are two options for this
**            parameter;
**            TASK_WAIT - the calling function will wait for a period
**            specified in the parameter 'milliSecsToWait'.
**            TASK_NOWAIT - the calling task will not wait for a token if
**            it is unavailable. Instead it will return immediately indicating
**            that the token was not available.
**          milliSecsToWait, this parameter only has meaning if 'waitMode' is
**            set to 'TASK_WAIT'. In this case, the calling function will wait
**            for a token to be freed, for the specified number of operating
**            system timer ticks. If a value of 0 is specified for this
**            parameter then the calling task will block forever, unless a
**            token becomes available.
**
** Outputs: NONE.
**
** Returns: SUCCESS, no errors.
**          OSP_NO_TOKENS_AVAILABLE, no semaphore tokens are free.
**          OSP_SEMAPHORE_TIMEOUT, timeout while awaiting a token.
**          FAILURE, RTOS specific errors.
*****************************************************************************/
S32 OSPSemaphoreGetToken(U32 semaphoreID, U32 waitMode,
                           U32 milliSecsToWait)
{
    int err;

    err = Os_SemWait(semaphoreID,milliSecsToWait);
    return err;
}

/*****************************************************************************
** Function: OSPSemaphoreReturnToken(): This function simply returns a token
** to the specified semaphore. There is no effective upper limit on the token
** count - irrespective of what the initial token count was when the Semaphore
** was created. For this reason, repetitive returning of a token will not
** result in an error. Semaphores used in such a way are thought of as
** 'counting' semaphores.
**
** Inputs:  semaphoreId, the unique handle that is used to reference the
**            semaphore in question.
**
** Outputs: NONE.
**
** Returns: SUCCESS, no errors.
**          FAILURE, RTOS specific errors.
*****************************************************************************/
S32 OSPSemaphoreReturnToken(U32 semaphoreID)
{
    return Os_SemPost(semaphoreID);
}


/*****************************************************************************
** Function: OSPTaskCreate(): This function will cause the named task to be
** created and added to the queue of ready tasks awaiting kernel dispatch.
**
** Inputs:  name[], a four character unique name for the task to be created.
**          stackSize, the size of the stack for this particular task.
**          entryPoint, a function pointer to the function that will be the
**            task.
**          priority, the initial task priority.
**          arg1, an argument that can be passed to the task.
**          arg2, an argument that can be passed to the task..
**          taskId, a pointer to hold the returned unique handle for the
**            created task.
**
** Outputs: NONE.
**
** Returns: SUCCESS, task created and started successfully.
**          FAILURE, RTOS specific errors.
*****************************************************************************/
S32 OSPTaskCreate(char name[], U32 stackSize, void (*entryPoint)(),
                    S32 priority, U32 arg1, U32 arg2,
                    U32 *taskId)
{
	*taskId = ThreadCreate(name,priority, 0, stackSize, entryPoint, arg1, arg2, 0, 0);
	return (*taskId ? SUCCESS : FAILURE);
}

S32 OSPTaskDelete(U32 taskId)
{
	E_ERR_CODE Err = OK;
	return Err;
}

/*****************************************************************************
** Function: OSPTaskTemporarySleep(): This function will cause the calling
** task to enter a sleep state for the number of milli seconds specified
** as the only parameter. Following the expiration of the specified tick count,
** the task will re-enter a ready state, awaiting dispatch by the kernel.
**
** Inputs:  numberOfTimerTicks, is the number of timer-ticks for which the
**            calling task is to sleep, this value is in milli seconds, but is
**            limited by the frequency of the clock interrupt.
**
** Outputs: NONE.
**
** Returns: SUCCESS, no errors.
**          OSP_WARNING, RTOS specific warnings.
**          FAILURE, RTOS specific errors.
*****************************************************************************/
S32 OSPTaskTemporarySleep(U32 milliSecsToWait)
{
    /* Make sure we're not in a LISR */
    MP_Assert(OSPInLISR == 0);
    if (OSPInLISR != 0)
    {
        return FAILURE;
    }

    Os_ThreadDelayMs(milliSecsToWait);

    return SUCCESS;
}


#define intLock()     1
#define intUnlock(x)
int Osp_Mutex;
void task_lockcreat(void)
{
    Osp_Mutex = Os_MutexInit();
}

void task_lock(void)
{
    Os_MutexLock(Osp_Mutex);
}

void task_unlock(void)
{
    Os_MutexUnlock(Osp_Mutex);
}

void task_lockdelete(void)
{
    Os_MutexDestroy(Osp_Mutex);
}

int EXCStartCriticalSection(void)
{
    task_lock();
    return intLock ();
}

/******************************************************************************
** Function:    EXCEndCriticalSection
**
** Inputs:      state  - Lock key returned from EXCStartCriticalSection
**
** Ouputs:      None.
**
** Returns:     Nothing.
**
** Description: This routine ends a critical section by calling intUnlock()
**              to reenable interrupts and STOS_TaskUnlock() to resume task
**              scheduling.
**
******************************************************************************/

void EXCEndCriticalSection(S32 state)
{
   intUnlock(state);
   task_unlock();
}


void taskDelay(S32 ticks)
{
	usleep(ticks * 1000);
}

/********************** test functions**********************/


